﻿using Roslyn.Compilers.CSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace QInjection.Injector
{
    internal class OperatorCategoryMap
    {
        private static volatile OperatorCategoryMap instance;
        private static object syncRoot = new Object();

        private Dictionary<OperatorCategory, Operator[]> _map;

        internal OperatorCategoryMap()
        {
            _map = new Dictionary<OperatorCategory, Operator[]>();

            // Operational Classification

            _map[OperatorCategory.None] = new Operator[] { };

            _map[OperatorCategory.Comparison] = new Operator[] 
            {
                Operator.Equals,
                Operator.NotEquals,
                Operator.GreaterThan,
                Operator.GreaterThanEquals,
                Operator.LessThan,
                Operator.LessThanEquals
            };

            _map[OperatorCategory.Mathematical] = new Operator[] 
            {
                Operator.PlusPlus,
                Operator.MinusMinus,
                Operator.Plus,
                Operator.Minus,
                Operator.Product,
                Operator.Division,
                Operator.Remainder
            };

            _map[OperatorCategory.Logical] = new Operator[] 
            {
                Operator.LogicalNot,
                Operator.LogicalAnd,
                Operator.LogicalOr
            };

            _map[OperatorCategory.Bitwise] = new Operator[] 
            {
                Operator.BitwiseAnd,
                Operator.BitwiseOr,
                Operator.BitwiseXor,
                Operator.BitwiseComplement
            };

            _map[OperatorCategory.Shifting] = new Operator[] 
            {
                Operator.ShiftRight,
                Operator.ShiftLeft
            };

            _map[OperatorCategory.Unary] = new Operator[]
            {
                Operator.BitwiseComplement,
                Operator.MinusMinus,
                Operator.PlusPlus,
                Operator.LogicalNot
            };

        }

        internal static OperatorCategoryMap Instance
        {
            get
            {
                if (instance == null)
                {
                    lock (syncRoot)
                    {
                        if (instance == null)
                            instance = new OperatorCategoryMap();
                    }
                }

                return instance;
            }
        }

        internal Operator[] this[OperatorCategory index]
        {
            get
            {
                if (instance == null)
                    throw new Exception("Singleton OperatorCategoryMap not instanciated");
                return instance._map[index];
            }
        }
    }
}
